/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.util;
import java.util.HashSet;
import java.util.Iterator;
/** A task that may be executed in a separate thread and permits examination of its status.
* Other threads can check if it is finished or wait for it
* to finish.
* <P>
* For example:
* <p><code><PRE>
* Runnable r = new Runnable () {
* public void run () {
* // do something
* }
* };
* Task task = new Task (r);
* RequestProcessor.postRequest (task);
* </PRE></code>
* <p>In a different thread one can then test <CODE>task.isFinished ()</CODE>
* or wait for it with <CODE>task.waitFinished ()</CODE>.
*
* @author Jaroslav Tulach
*/
public class Task extends Object implements Runnable {
/** Dummy task which is already finished. */
public static final Task EMPTY = new Task(null);
/** what to run */
private Runnable run;
/** flag if we have finished */
private boolean finished;
/** listeners for the finish of task (TaskListener)
* @associates TaskListener*/
private HashSet list;
/** Create a new task.
* The runnable should provide its own error-handling, as
* by default thrown exceptions are simply logged and not rethrown.
* @param run runnable to run that computes the task
*/
public Task(Runnable run) {
this.run = run;
if (run == null) {
finished = true;
}
}
/** Test whether the task has finished running.
* @return <code>true</code> if so
*/
public final boolean isFinished () {
return finished;
}
/** Wait until the task is finished.
*/
public final void waitFinished () {
waitFinishedImpl();
}
/** This method is an implementation of the waitFinished method
* This implemetation run the task and then returns.
*/
void waitFinishedImpl () {
if (!finished) {
synchronized (this) {
while (!finished) {
try {
wait ();
} catch (InterruptedException ex) {
}
}
}
}
}
/** Notify all waiters that this task has finished.
* @see #run
*/
protected final void notifyFinished () {
Iterator it;
synchronized (this) {
finished = true;
notifyAll ();
// fire the listeners
if (list == null) return;
it = ((HashSet)list.clone ()).iterator ();
}
while (it.hasNext ()) {
TaskListener l = (TaskListener)it.next ();
l.taskFinished (this);
}
}
/** Start the task.
* When it finishes (even with an exception) it calls
* {@link #notifyFinished}.
* Subclasses may override this method, but they
* then need to call {@link #notifyFinished} explicitly.
* <p>Note that this call runs synchronously, but typically the creator
* of the task will call this method in a separate thread.
*/
public void run () {
try {
finished = false;
if (run != null) run.run ();
} catch (Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath)t;
}
if (System.getProperty ("netbeans.debug.exceptions") != null) {
System.out.println("Exception occurred in request processor:"); // NOI18N
t.printStackTrace ();
}
} finally {
notifyFinished ();
}
}
/** Add a listener to the task.
* @param l the listener to add
*/
public synchronized void addTaskListener (TaskListener l) {
if (list == null) list = new HashSet ();
list.add (l);
if (finished) {
l.taskFinished(this);
}
}
/** Remove a listener from the task.
* @param l the listener to remove
*/
public synchronized void removeTaskListener (TaskListener l) {
if (list == null) return;
list.remove (l);
}
public String toString () {
return "task " + run; // NOI18N
}
}
/*
* Log
* 14 Gandalf 1.13 1/12/00 Pavel Buzek I18N
* 13 Gandalf 1.12 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 12 Gandalf 1.11 8/11/99 Jaroslav Tulach Contains debugging code
* 11 Gandalf 1.10 7/28/99 Jaroslav Tulach Solves LineSet
* starvation.
* 10 Gandalf 1.9 7/25/99 Ian Formanek Exceptions printed to
* console only on "netbeans.debug.exceptions" flag
* 9 Gandalf 1.8 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 8 Gandalf 1.7 5/16/99 Ian Formanek Better safety against
* errors in tasks
* 7 Gandalf 1.6 5/15/99 Jesse Glick [JavaDoc]
* 6 Gandalf 1.5 4/24/99 Jaroslav Tulach
* 5 Gandalf 1.4 4/21/99 Petr Hamernik empty task is finished.
* 4 Gandalf 1.3 4/13/99 Petr Hamernik deadlocks prevention
* 3 Gandalf 1.2 4/8/99 Petr Hamernik checking deadlocks in
* RequestProcessor
* 2 Gandalf 1.1 2/11/99 David Simonek
* 1 Gandalf 1.0 1/5/99 Ian Formanek
* $
*/